package com.smartao.core.orm.entity;

import java.io.Serializable;
import java.lang.reflect.Member;
import java.util.Map;

import javax.persistence.GeneratedValue;
import javax.persistence.Id;
import javax.persistence.MappedSuperclass;

import org.apache.struts2.json.annotations.JSONFieldBridge;
import org.hibernate.annotations.GenericGenerator;

import com.opensymphony.xwork2.conversion.TypeConverter;
import com.smartao.core.orm.mybatis.EntityTypeHandler;
import com.smartao.util.ReflectionUtils;

/**
 * Entity基类.<br>
 * ID为Long型<br>
 * 基类统一定义id的属性名称、数据类型、列名映射及生成策略.<br>
 * @author Ricky
 */
@MappedSuperclass
public class BaseEntity<T extends BaseEntity<T>> extends EntityTypeHandler<T> implements TypeConverter,Serializable {

	private static final long serialVersionUID = 9071309727314398599L;
	
	@Id
	@GeneratedValue(generator = "longIdGenerator")
	@GenericGenerator(name = "longIdGenerator", strategy = "com.smartao.core.orm.entity.LongIdGenerator")
	protected Long id;

	@JSONFieldBridge
	public Long getId() {
		return id;
	}

	public void setId(Long id) {
		this.id = id;
	}
	
	@Override
	@SuppressWarnings("unchecked")
	public Class<T> getEntityClass() {
		return (Class<T>) ReflectionUtils.getSuperClassGenricType(getClass());
	}
	
	@Override
	@SuppressWarnings({ "rawtypes", "unchecked" })
	public Object convertValue(Map<String, Object> context, Object target, Member member,
            String propertyName, Object value, Class toType) {
		//toType必须是BaseEntity的子类才做转换
		if(BaseEntity.class.isAssignableFrom(toType)){
			try{
				String[] values = (String[])value;
				Long id = Long.valueOf(values[0]);
				return getEntityInstance(id,toType);
			}catch(Exception e){
				logger.error(e.getMessage(),e);
				return null;
			}
		}else {
        	return null;
        }
    }
	
	@Override
	public int hashCode() {
		final int prime = 31;
		int result = 1;
		result = prime * result + ((id == null) ? 0 : id.hashCode());
		return result;
	}

	@Override
	public boolean equals(Object obj) {
		if (this == obj)
			return true;
		if (obj == null)
			return false;
		if (getClass() != obj.getClass())
			return false;
		BaseEntity<?> other = (BaseEntity<?>) obj;
		if (id == null) {
			if (other.id != null)
				return false;
		} else if (!id.equals(other.id))
			return false;
		return true;
	}

}
